<template>
  <ElDialog
    v-model="visible"
    title="菜单权限"
    width="520px"
    align-center
    class="el-dialog-border"
    @close="handleClose"
  >
    <ElScrollbar height="70vh">
      <ElTree
        ref="treeRef"
        :data="processedMenuList"
        show-checkbox
        node-key="id"
        :default-expand-all="isExpandAll"
        :default-checked-keys="[1, 2, 3]"
        :props="defaultProps"
        @check="handleTreeCheck"
      >
        <template #default="{ data }">
          <div style="display: flex; align-items: center">
            <span v-if="data.isAuth">
              {{ data.label }}
            </span>
            <span v-else>{{ defaultProps.label(data) }}</span>
          </div>
        </template>
      </ElTree>
    </ElScrollbar>
    <template #footer>
      <div class="dialog-footer">
        <ElButton @click="outputSelectedData" style="margin-left: 8px">获取选中数据</ElButton>

        <ElButton @click="toggleExpandAll">{{ isExpandAll ? '全部收起' : '全部展开' }}</ElButton>
        <ElButton @click="toggleSelectAll" style="margin-left: 8px">{{
          isSelectAll ? '取消全选' : '全部选择'
        }}</ElButton>
        <ElButton type="primary" @click="savePermission">保存</ElButton>
      </div>
    </template>
  </ElDialog>
</template>

<script setup lang="ts">
  import {
    assignRolePermissions,
    fetchGetAllPermissions,
    getRolePermissions
  } from '@/api/system-manage'
  import { formatMenuTitle } from '@/router/utils/utils'
  import type { AppRouteRecord } from '@/types/router'

  type RoleListItem = Api.SystemManage.RoleListItem

  interface Props {
    modelValue: boolean
    roleData?: RoleListItem
  }

  interface Emits {
    (e: 'update:modelValue', value: boolean): void
    (e: 'success'): void
  }

  const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    roleData: undefined
  })

  const emit = defineEmits<Emits>()

  const menuList = ref<AppRouteRecord[]>([])
  const treeRef = ref()
  const isExpandAll = ref(true)
  const isSelectAll = ref(false)

  /**
   * 弹窗显示状态双向绑定
   */
  const visible = computed({
    get: () => props.modelValue,
    set: (value) => emit('update:modelValue', value)
  })

  /**
   * 菜单节点类型
   */
  interface MenuNode {
    id?: string
    name?: string | symbol
    label?: string | symbol
    meta?: {
      title?: string
      authList?: Array<{
        id?: string
        authMark: string
        title: string
        checked?: boolean
      }>
    }
    children?: MenuNode[]
    [key: string]: any
  }

  /**
   * 处理菜单数据，将 authList 转换为树形子节点
   * 递归处理菜单树，将权限列表展开为可选择的子节点
   */
  const processedMenuList = computed(() => {
    // 直接转换菜单数据为树形结构
    const processMenuData = (menuData: AppRouteRecord[]): MenuNode[] => {
      return menuData.map((item): MenuNode => {
        const processed: MenuNode = {
          id: item.id,
          name: item.name,
          label: item.meta?.title || item.name,
          meta: item.meta,
          children: item.children ? processMenuData(item.children) : undefined
        }

        // 如果有 authList，将其转换为子节点
        if (item.meta?.authList?.length) {
          const authNodes: MenuNode[] = item.meta.authList.map((auth) => ({
            id: `${auth.id}`,
            name: `${auth.title}`,
            label: auth.title,
            authMark: auth.authMark,
            isAuth: true,
            checked: false
          }))

          processed.children = processed.children
            ? [...processed.children, ...authNodes]
            : authNodes
        }

        return processed
      })
    }

    return processMenuData(menuList.value)
  })

  /**
   * 树形组件配置
   */
  const defaultProps = {
    children: 'children',
    label: (data: any) => formatMenuTitle(data.meta?.title) || data.label || ''
  }

  /**
   * 加载菜单数据
   */
  const loadMenuData = async () => {
    try {
      const data = await fetchGetAllPermissions()
      menuList.value = data || []
    } catch (error) {
      console.error('加载菜单数据失败:', error)
      ElMessage.error('加载菜单数据失败')
      menuList.value = []
    }
  }

  /**
   * 监听弹窗打开，初始化权限数据
   */
  watch(
    () => props.modelValue,
    async (newVal) => {
      if (newVal && props.roleData) {
        try {
          // 加载菜单数据
          await loadMenuData()

          // 获取角色已有的权限ID集合
          const response = await getRolePermissions(props.roleData.roleId.toString())
          const permissionIds = response || []

          // 将权限ID转换为树节点的key
          const checkedKeys = permissionIds.map((id: string | number) => id.toString())

          // 设置树形组件的选中状态
          treeRef.value?.setCheckedKeys(checkedKeys)

          // 更新全选按钮状态
          handleTreeCheck()
        } catch (error) {
          console.error('加载角色权限失败:', error)
          ElMessage.error('加载角色权限失败')
        }
      }
    }
  )

  /**
   * 关闭弹窗并清空选中状态
   */
  const handleClose = () => {
    visible.value = false
    treeRef.value?.setCheckedKeys([])
  }

  /**
   * 保存权限配置
   */
  const savePermission = async () => {
    if (!props.roleData) {
      ElMessage.warning('请选择角色')
      return
    }

    try {
      const tree = treeRef.value
      if (!tree) {
        ElMessage.warning('权限树未初始化')
        return
      }

      // 获取选中的权限ID
      const checkedKeys = tree.getCheckedKeys()
      const halfCheckedKeys = tree.getHalfCheckedKeys()

      // 合并选中的权限ID（全选和半选）
      const allCheckedKeys = [...checkedKeys, ...halfCheckedKeys]

      // 过滤出有效的权限ID（去除空值和无效值）
      const validPermissionIds = allCheckedKeys
        .filter((key) => key && typeof key === 'string' && key.length > 0)
        .map((key) => key.toString())

      // 调用API保存权限
      await assignRolePermissions(props.roleData.roleId.toString(), validPermissionIds)

      ElMessage.success('权限保存成功')
      emit('success')
      handleClose()
    } catch (error) {
      console.error('保存权限失败:', error)
      ElMessage.error('权限保存失败')
    }
  }

  /**
   * 切换全部展开/收起状态
   */
  const toggleExpandAll = () => {
    const tree = treeRef.value
    if (!tree) return

    const nodes = tree.store.nodesMap
    // 这里保留 any，因为 Element Plus 的内部节点类型较复杂
    Object.values(nodes).forEach((node: any) => {
      node.expanded = !isExpandAll.value
    })

    isExpandAll.value = !isExpandAll.value
  }

  /**
   * 切换全选/取消全选状态
   */
  const toggleSelectAll = () => {
    const tree = treeRef.value
    if (!tree) return

    if (!isSelectAll.value) {
      const allKeys = getAllNodeKeys(processedMenuList.value)
      tree.setCheckedKeys(allKeys)
    } else {
      tree.setCheckedKeys([])
    }

    isSelectAll.value = !isSelectAll.value
  }

  /**
   * 递归获取所有节点的 key
   * @param nodes 节点列表
   * @returns 所有节点的 key 数组
   */
  const getAllNodeKeys = (nodes: MenuNode[]): string[] => {
    const keys: string[] = []
    const traverse = (nodeList: MenuNode[]): void => {
      nodeList.forEach((node) => {
        if (node.id) keys.push(node.id)
        if (node.children?.length) traverse(node.children)
      })
    }
    traverse(nodes)
    return keys
  }

  /**
   * 处理树节点选中状态变化
   * 同步更新全选按钮状态
   */
  const handleTreeCheck = () => {
    const tree = treeRef.value
    if (!tree) return

    const checkedKeys = tree.getCheckedKeys()
    const allKeys = getAllNodeKeys(processedMenuList.value)

    isSelectAll.value = checkedKeys.length === allKeys.length && allKeys.length > 0
  }

  /**
   * 输出选中的权限数据到控制台
   * 用于调试和查看当前选中的权限配置
   */
  const outputSelectedData = () => {
    const tree = treeRef.value
    if (!tree) return

    const selectedData = {
      checkedKeys: tree.getCheckedKeys(),
      halfCheckedKeys: tree.getHalfCheckedKeys(),
      checkedNodes: tree.getCheckedNodes(),
      halfCheckedNodes: tree.getHalfCheckedNodes(),
      totalChecked: tree.getCheckedKeys().length,
      totalHalfChecked: tree.getHalfCheckedKeys().length
    }

    console.log('=== 选中的权限数据 ===', selectedData)
    ElMessage.success(`已输出选中数据到控制台，共选中 ${selectedData.totalChecked} 个节点`)
  }
</script>

<style lang="scss" scoped>
  .dialog-footer {
    display: flex;
    gap: 12px;
    justify-content: flex-end;
  }
</style>
